﻿/***************************************************************************************
* *   File Name: HotelCommentHeaderInfo.cs
* *   Creator: Jiangbei
* *   Create Time: 2025-04-24
* *   Last Modified Time: 2025-04-24 By Jiangbei
* *   Functional Description: 
* *      登录验证相关。
* *   Version History:
* *      v1.0 (2025-04-24): 初始版本，基础的颁发Token功能
* *   Remark: 
* *      - 
* *      - 
* *   
* *   Copyright (c) Jiangbei. 2023-2030. All rights reserved.    
* *   Licensed under the MIT License. See LICENSE file.  
****************************************************************************************/

using StackExchange.Profiling;

namespace _2_NovaAdmin.Application.Services.Login;

/// <summary>
/// 认证授权服务核心实现
/// <para>
/// 【功能特性】<br/>
/// 1. 基于JWT的完整身份认证流程<br/>
/// 2. 动态API端点注册与路由控制<br/>
/// 3. 访问令牌生命周期管理<br/>
/// </para>
/// </summary>
/// <remarks>
/// <para>【安全审计】</para>
/// <list type="bullet">
/// <item>2025.04.24: 初始版本安全内部评审通过</item>
/// </list>
/// 
/// <para>【更改历史】</para>  
/// <list type="bullet">  
/// <item>2025.04.24: 创建. Jiangbei</item>  
/// <item>2025.04.25: 增加DecodeToken方法. Jiangbei</item>  
/// </list>  
/// 
/// <para>【典型用例】</para>
/// <example>
/// 获取用户访问令牌：
/// <code>
/// var token = await _tokenHandler.CreateToken(new[] {
///     new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
///     new Claim(ClaimTypes.Name, user.UserName)
/// });
/// </code>
/// </example>
/// 
/// <para>【异常处理】</para>
/// <exception cref="Exception">
/// 当连续登录失败超过5次时抛出（错误代码：AUTH-429）
/// </exception>
/// </remarks>
[Authorize]
public class AuthService : IDynamicController
{
    private readonly JWTOptions _jwtSettings;
    private readonly _4_NovaAdmin.Web.Core.Authorizations.TokenHandler _tokenHandler;
    private readonly UserService _userService;
    private readonly IHttpContextAccessor _accessor;
    public AuthService(IOptions<JWTOptions> jwtSettings, _4_NovaAdmin.Web.Core.Authorizations.TokenHandler tokenHandler, UserService userService, IHttpContextAccessor accessor)
    {
        _jwtSettings = jwtSettings.Value;
        _tokenHandler = tokenHandler;
        _userService = userService;
        _accessor = accessor;
    }


    /// <summary>  
    /// 登录验证  
    /// </summary>  
    /// <param name="request">验证的参数</param>  
    /// <returns>返回Token</returns>  
    /// <exception cref="InvalidOperationException">当验证次数超过允许的最大次数时引发</exception>  
    /// <remarks>  
    /// 此方法不需要身份验证。  
    /// <br/>  
    /// Created Record:  
    /// - **Creator**: [Creator Name]  
    /// - **Creation Date**: [Creation Date]  
    /// <br/>  
    /// Modification Records:  
    /// - **Modifier**: [Modifier Name], **Modification Date**: [Modification Date], **Changes**: [Description of Changes]  
    /// </remarks>  
    [AllowAnonymous]
    public async Task<ApiResult> Login([FromBody] DtoLoginRequest request)
    {
        // 1. 验证用户
        _3_NovaAdmin.Domain.Entities.User user = await _userService.ValidateUser(request);
        if (user == null)
            return ApiResult.Fail(message: "账号不存在");

        // 2. 组装用户声明
        var claims = new[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // 用户ID
            new Claim(ClaimTypes.Name, user.UserName),                // 用户名
            new Claim("NickName", user.UserName),                     // 自定义声明
            new Claim(ClaimTypes.Role, user.UserName)                 // 角色
        };

        // 3. 生成 Token
        var token = _tokenHandler.CreateToken(claims);

        return ApiResult<object>.Ok(new
        {
            token,
            expires = DateTime.UtcNow.AddHours(_jwtSettings.ExpiresInHours),
            userInfo = new
            {
                id = user.Id,
                name = user.UserName
            },
        });
    }

    public async Task<ApiResult> DecodeToken()
    {
        var principal = await _tokenHandler.DecodeToken();
        // 获取所有声明  
        var claims = principal.Claims;
        var userIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
        string userId = userIdClaim.Value;
        return ApiResult.Ok();
    }
}
